/**
 * 
 */
package edu.umd.clip.lm.model.training.metrics;

import org.w3c.dom.Element;

import edu.umd.clip.lm.model.training.ContextVariable;
import edu.umd.clip.lm.model.training.ContextVariableStats;
import edu.umd.clip.lm.util.ConstCountDistribution;
import edu.umd.clip.lm.util.CountDistribution;
import edu.umd.clip.lm.util.Long2IntMap;
import edu.umd.clip.lm.util.ProbMath;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class RelativeConditionalEntropy extends ContextVariableMetrics {

	public RelativeConditionalEntropy() {
		super("Information Gain: H(w|x) / H(x)");
	}
	
	
	public RelativeConditionalEntropy(Element elem) {
		super(elem);
	}


	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.metrics.ContextVariableMetrics#computeScore(edu.umd.clip.lm.model.training.ContextVariable, edu.umd.clip.lm.model.training.ContextVariableStats)
	 */
	@Override
	public double computeScore(ContextVariable ctxVar, ContextVariableStats stat) {
		long totalCount = 0;
		double condEntropy = 0;
		for(Object d : stat.x2wDistributions.values()) {
			ConstCountDistribution dist = (ConstCountDistribution) d;
			
			long counts[] = dist.values();
			for(long count : counts) {
				condEntropy -= count * ProbMath.log2(count);
			}
			condEntropy += dist.getTotalCount() * ProbMath.log2(dist.getTotalCount());
			totalCount += dist.getTotalCount();
		}
		condEntropy /= totalCount;
		
		double entropy = 0;
		for(long count : stat.contextCounts.values() ) {
			entropy -= count * ProbMath.log2(count);
		}
		entropy = entropy / totalCount + ProbMath.log2(totalCount);
		
		return condEntropy / entropy;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.metrics.ContextVarStatUser#needContextVarCounts()
	 */
	@Override
	public boolean needContextVarCounts() {
		return true;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.metrics.ContextVarStatUser#needVarToWordCounts()
	 */
	@Override
	public boolean needVarToWordCounts() {
		return true;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.metrics.ContextVarStatUser#needWordCounts()
	 */
	@Override
	public boolean needWordCounts() {
		return false;
	}

	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.model.training.metrics.ContextVarStatUser#needWordToVarCounts()
	 */
	@Override
	public boolean needWordToVarCounts() {
		return false;
	}

}
